#encoding=utf8
'''
Created on Nov 25, 2014

@author: jingyang <jingyang@smalltreemedia.com>
'''
from functools import partial

from django.contrib import admin, messages
from django.utils import timezone
from django.forms.models import modelformset_factory
from django.contrib.admin import widgets
from django.contrib.admin.options import get_ul_class
from django.contrib.auth.models import User

from sub_info.models import SubInfo, UPDATE_PURPOSE, UPDATE_ASSETS, UPDATE_META,\
    RESUB_REQ, ReviewStatus, ReviewStatusRecord, Rejection, RejReason, RejImg,\
    RejAct
from sub_info.forms import SubInfoForm, RejImgForm
from utils import field, email_sending, api_call
from core.widgets import CustomForeignKeyRawIdWidget
from app_info.models import SPECIAL_SETTINGS, AppVersion
from threads import UpdateGoogleSheetThread
import settings
from core.tasks import update_google_sheet
from django.shortcuts import get_object_or_404
from sorl.thumbnail.shortcuts import get_thumbnail
import os
from notification.models import Notice
import json
from django.core.mail import mail_admins
from qa_info.models import DevQAInfo, ReleaseQAInfo
from django.core.urlresolvers import reverse


class SubInfoAdmin(admin.ModelAdmin):
    list_display = ('request_id', 'get_app', 'version',
        'is_resub',
        'get_editor', 'get_edqa',
        'edsr', 'validation', 'get_valid_date',
#        'get_binary_status', 'get_meta_status', 'get_binary_upload_status',
        'get_status', 'review_status')
    raw_id_fields = ('app', 'rej')
#    list_editable = ('validation', 'validation_notes', 'binary_status', 'meta_status',
#        'binary_upload_status', 'status')
    list_filter = ('editor', 'release', 'validation', 'status', 'is_resub', 'review_status')
    search_fields = ('app__prj_code', 'app__old_prj_code', 'request_id')
    list_per_page = 20
    form = SubInfoForm
    notice_content = '''
    <p>Submission Request ID: <a href='/admin/sub_info/subinfo/{0}/'>{1}</a></p>
    <p>App Code: <b>{2}</b></p>
    <p>App Name: <b>{3}</b></p>
    <p>App Version: <b>{4}</b></p>
    '''
    fieldsets = (
        ('App Info', {
            'fields':
            (
            'app',
#            'type',
#            'update_for',
            'is_resub',
            'version',
            'rej',
            'resub_req',
            )
        }),
#         ('QA Request', {
#             'fields':
#             (
#             'edqa',
#             'etqa',
# #            'programmer',
#             'notes_to_qa',
#             )
#         }),
        ('Marketing Ops Request', {
            'fields':
            (
            'edsr',
            'price',
            'prefix',
            'update_assets',
            'update_meta',
            'rating',
            'notes',
            'release',
            )
        }),
        ('Validation', {
            'fields':
            (
            'validation',
            'valid_date',
            'validation_notes',
            )
        }),
        ('Submission Progress', {
            'fields':
            (
#            ('binary_status', 'binary_ready_date'),
#            ('meta_status', 'meta_ready_date'),
#            ('binary_upload_status', 'binary_uploaded_date'),
            ('status', 'app_submit_date', 'sub_person'),
            )
        }),
    )

    class Media:
        js = ('base/js/custom_sub_admin.js', 'base/js/RelatedObjectLookups.js')

    def get_fieldsets(self, request, obj=None):
        if obj and not obj.validation == 'I':
            f = (
                ('Request Info', {
                    'fields':
                    (
                    'request_id',
                    'create_time',
                    'editor',
                    )
                }),
                ('App Info', {
                    'fields':
                    (
                    'get_app',
                    'version',
                    'get_type',
                    'get_purpose',
                    'get_notes',
                    'is_resub',
                    'get_rej',
                    'get_resub_req',
                    'get_product_owner',
                    'get_programmer',
                    'get_ref_id',
                    'get_app_store',
                    'get_bundle_id',
                    'get_apple_id',
                    'get_display_name',
                    ('get_has_ads', 'get_ads_requests'),
                    ('get_has_cross_promo', 'get_cross_promo_requests'),
                    ('get_has_iap', 'get_iap_requests'),
                    'get_special_settings',
                    )
                }),
#                 ('QA Request', {
#                     'fields':
#                     (
#                     'get_edqa',
#                     'get_etqa',
#                     'notes_to_qa',
#                     'get_dev_qa_req_display',
#                     )
#                 }),
                ('Marketing Ops Request', {
                    'fields':
                    (
                    'get_submission_doc_local',
                    'get_submission_doc_remote',
                    'edsr',
                    'get_price',
                    'prefix',
                    'get_territories',
                    'territories',
                    'get_update_assets',
                    'get_update_meta',
                    'rating',
                    'notes',
                    'release',
                    )
                }),
                ('Validation', {
                    'fields':
                    (
                    'validation',
                    'valid_date',
                    'validation_notes',
                    )
                }),
            )
            if obj.validation == 'V':
                lf = list(f)
                lf.append(('Submission Progress', {
                    'fields':
                    (
#                    'binary_status', 'binary_ready_date',
#                    'meta_status', 'meta_ready_date',
#                    'binary_upload_status', 'binary_uploaded_date',
                    'get_status',
                    'app_submit_date',
                    'sub_person',
                    )
                }))
                return tuple(lf)
            return f
        else:
            return (
                ('App Info', {
                    'fields':
                    (
                    'app',
                    'version',
                    'is_resub',
#                    'type',
#                    'update_for',
                    'rej',
#                     'resub_req',
                    )
                }),
#                 ('QA Request', {
#                     'fields':
#                     (
#                     'edqa',
#                     'etqa',
# #                    'programmer',
#                     'notes_to_qa',
#                     )
#                 }),
                ('Marketing Ops Request', {
                    'fields':
                    (
                    'edsr',
                    'price',
                    'prefix',
                    'update_assets',
                    'update_meta',
                    'rating',
                    'notes',
                    'release',
                    )
                }),
            )
        if self.declared_fieldsets:
            return self.declared_fieldsets
        form = self.get_form(request, obj)
        fields = list(form.base_fields) + list(self.get_readonly_fields(request, obj))
        return [(None, {'fields': fields})]

    def get_readonly_fields(self, request, obj=None):
        fields = ('request_id', 'create_time', 'editor', 'get_app_store',
            'get_bundle_id', 'get_apple_id', 'get_display_name', 'get_has_ads',
            'get_ads_requests', 'get_cross_promo_requests', 'get_iap_requests',
            'get_has_cross_promo', 'get_has_iap', 'get_special_settings',
            'app', 'get_app', 'get_purpose', 'get_type',
            'version', 'is_resub', 'rej', 'get_rej', 'resub_req', 'get_resub_req',
            'edqa', 'get_edqa', 'etqa', 'get_etqa', 'get_programmer', 'get_ref_id',
            'notes_to_qa', 'edsr', 'price', 'get_price', 'territories', 'update_assets',
            'get_update_assets', 'update_meta', 'get_update_meta',
            'get_territories', 'rating', 'notes', 'release',
            'get_submission_doc_local', 'get_submission_doc_remote',
            'get_notes', 'get_product_owner', 'status', 'get_status', 'app_submit_date', 'sub_person',
            'get_dev_qa_req_display')
        if obj and not obj.validation == 'I':
            if request.user.is_superuser or request.user.groups.filter(name='Post-production Staff').exists():
                return fields
            return fields + ('validation', 'valid_date', 'validation_notes',
#                'binary_status', 'binary_ready_date', 'meta_status', 'meta_ready_date',
#                'binary_upload_status', 'binary_uploaded_date',
                'status', 'app_submit_date', 'sub_person')
        return self.readonly_fields

    @field('Binary File Ready', boolean=True, admin_order_field='binary_status')
    def get_binary_status(self, obj):
        return obj.binary_status == 'Y'

    @field('Meta Data Ready', boolean=True, admin_order_field='meta_status')
    def get_meta_status(self, obj):
        return obj.meta_status == 'Y'

    @field('Binary File Uploaded', boolean=True, admin_order_field='binary_upload_status')
    def get_binary_upload_status(self, obj):
        return obj.binary_upload_status == 'Y'

    @field('Submission Status', allow_tags=True, admin_order_field='status')
    def get_status(self, obj):
        if not obj.status:
            return "<img src='/static/admin/img/icon-no.gif' alt='False'>"
        if obj.status == 'S':
            return "<img src='/static/admin/img/icon-yes.gif' alt='True'>"
        else:
            return obj.get_status_display()

    @field('Rejection', allow_tags=True)
    def get_rej(self, obj):
        return "<a href='/admin/sub_info/rejection/%s/' target='_blank'>%s</a>" %\
            (obj.rej_id, obj.rej.issue_id)

    @field('Validated Date', admin_order_field='valid_date')
    def get_valid_date(self, obj):
        return obj.valid_date.strftime('%Y-%m-%d') if obj.valid_date else ""

    @field('Price (USD)')
    def get_price(self, obj):
        return obj.get_price()

#    @field('Resub?', boolean=True, admin_order_field='is_resub')
#    def get_is_resub(self, obj):
#        return obj.is_resub == 'Y'

    def get_production_team(self, obj):
        team = None
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        try:
            team = version[0].prd_team.name
        except Exception as e:
            print e
        return team or 'N/A'

    @field('Product Owner', allow_tags=True)
    def get_product_owner(self, obj):
        owner = None
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        try:
            owner = version[0].product_owner
#            owner = User.objects.get(id=version[0].product_owner)
        except Exception, e:
            print e
        return owner or 'N/A'

    @field('Production Purpose - Detail Change List & Notes', allow_tags=True)
    def get_notes(self, obj, sp='<br />'):
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        return (sp.join(version[0].change_list.splitlines()) or "") if version else ""

    @field('Production Purpose', allow_tags=True)
    def get_purpose(self, obj, sp="<br />"):
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        if version:
            if version[0].purpose == 'New App':
                return "New App"
            data = str(version[0].purpose).replace('[', '').replace(']', '').\
                replace("u'", '').replace("'", '').split(', ')
            return sp.join([dict(UPDATE_PURPOSE).get(d, "") for d in data])
        return ""

    @field('Production Type')
    def get_type(self, obj):
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        return version[0].get_type_display() if version else ""

    @field('Programmer', allow_tags=True)
    def get_programmer(self, obj, display=True):
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        if version:
            if version[0].programmer:
                if display:
                    return version[0].programmer
                else:
                    import sys
                    reload(sys)
                    sys.setdefaultencoding('utf-8')
                    return u'%s' % version[0].programmer
        return "Unassigned"

    @field('Production Brief Ref ID')
    def get_ref_id(self, obj):
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        return version[0].ref_id or "" if version else ""

    @field('App Store')
    def get_app_store(self, obj):
        return obj.app.app_store

    @field('Bundle ID / Package Name')
    def get_bundle_id(self, obj):
        return obj.app.get_full_bundle_id()

    @field('Apple ID')
    def get_apple_id(self, obj):
        return obj.app.app_id

    @field('Submission Doc (Local)')
    def get_submission_doc_local(self, obj):
        extra_info = obj.app.appextrainfo if hasattr(obj.app, 'appextrainfo') else None
        return (extra_info.media_local or "") if extra_info else ""

    @field('Submission Doc (Dropbox)')
    def get_submission_doc_remote(self, obj):
        extra_info = obj.app.appextrainfo if hasattr(obj.app, 'appextrainfo') else None
        return (extra_info.media_remote or "") if extra_info else ""

    @field('Display Name on Device')
    def get_display_name(self, obj):
        extra_info = obj.app.appextrainfo if hasattr(obj.app, 'appextrainfo') else None
        return (extra_info.display_name or "") if extra_info else ""

    @field('Has Ads?', boolean=True)
    def get_has_ads(self, obj):
#        return obj.app.adsinfo_set.exists()
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        if version:
            return version[0].ads_required == 'Y'
        return False

    @field('Ads Requests', allow_tags=True)
    def get_ads_requests(self, obj):
        return "<br />".join(["<a href='/admin/ads_info/adsinfo/%s' target='_blank'>%s</a> - %s" %\
                              (i.pk, i.request_id, i.get_status_display())\
                              for i in obj.app.adsinfo_set.all()])

    @field('Has Cross Promo?', boolean=True)
    def get_has_cross_promo(self, obj):
#        return obj.app.adsinfo_set.filter(cross_promo='Y').exists()
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        if version:
            return version[0].cross_promo_required == 'Y'
        return False

    @field('Cross Promo Requests', allow_tags=True)
    def get_cross_promo_requests(self, obj):
        old = ["<a href='/admin/ads_info/adsinfo/%s' target='_blank'>%s</a> - %s" %
               (i.pk, i.request_id, i.get_status_display())
               for i in obj.app.adsinfo_set.filter(cross_promo='Y')]
        new = ["<a href={} target='_blank'>{}</a> - {}"
               .format(reverse("admin:ads_info_crosspromoreq_change", args=[r.pk]),
                       r, r.get_status_display())
               for r in obj.app.crosspromoreq_set.all()]
        return "<br />".join(old + new)

    @field('Has IAP?', boolean=True)
    def get_has_iap(self, obj):
#        return obj.app.iapinfo_set.filter(status='F').exists()
        version = obj.app.appversion_set.exclude(status='C').filter(code=obj.version)
        if version:
            return version[0].iap_required == 'Y'
        return False

    @field('IAP Requests', allow_tags=True)
    def get_iap_requests(self, obj):
        return "<br />".join(["<a href='/admin/iap_info/iapinfo/%s' target='_blank'>%s</a> - %s" %\
                              (i.pk, i.request_id, i.get_status_display())\
                              for i in obj.app.iapinfo_set.all()])

    @field('Special Settings', allow_tags=True)
    def get_special_settings(self, obj, sp="<br />"):
        extra_info = obj.app.appextrainfo if hasattr(obj.app, 'appextrainfo') else None
        if extra_info:
            if extra_info.special:
                data = str(extra_info.special).replace('[', '').replace(']', '').\
                    replace("u'", '').replace("'", '').split(', ')
                return sp.join([dict(SPECIAL_SETTINGS).get(d) for d in data])
        return ""

    @field('Estimated Date of QA', admin_order_field='edqa')
    def get_edqa(self, obj):
        return obj.edqa.strftime('%Y-%m-%d') if obj.edqa else ""

    @field('App', allow_tags=True, admin_order_field='app__prj_code')
    def get_app(self, obj):
        return "<a href='%s%s/' target='_blank'>%s</a>" % ('/admin/app_info/app/',
            obj.app_id, obj.app)

    @field('Editor', admin_order_field='editor')
    def get_editor(self, obj):
        return obj.editor.split('@')[0] if obj.editor else ""

#    @field('Update Purpose', allow_tags=True)
#    def get_update_for(self, obj):
#        if obj.update_for:
#            data = str(obj.update_for).replace('[', '').replace(']', '').\
#                replace("u'", '').replace("'", '').split(', ')
#            return "<br />".join([dict(UPDATE_PURPOSE).get(d) for d in data])
#        return ""

    @field('Update on Graphics Assets', allow_tags=True)
    def get_update_assets(self, obj, sp='<br />'):
        if obj.update_assets:
            data = str(obj.update_assets).replace('[', '').replace(']', '').\
                replace("u'", '').replace("'", '').split(', ')
            return sp.join([dict(UPDATE_ASSETS).get(d) for d in data])
        return ""

    @field('Update on Meta Data', allow_tags=True)
    def get_update_meta(self, obj, sp='<br />'):
        if obj.update_meta:
            data = str(obj.update_meta).replace('[', '').replace(']', '').\
                replace("u'", '').replace("'", '').split(', ')
            return sp.join([dict(UPDATE_META).get(d) for d in data])
        return ""

    @field('Estimate Time of QA')
    def get_etqa(self, obj):
        return "%s Day(s)" % obj.etqa

    @field('Territories')
    def get_territories(self, obj):
        return obj.get_territories()

    @field('Requests', allow_tags=True)
    def get_resub_req(self, obj):
        if obj.get_resub_req():
            return "<br />".join(["<font data-id='%s'>%s</font>" %\
                (d, dict(RESUB_REQ).get(d).split('-')[0]) for d in obj.get_resub_req()])
        return ""

    @field('Dev QA Request', allow_tags=True)
    def get_dev_qa_req_display(self, obj):
        rtn = ["<a href='/admin/qa_info/devqainfo/%s/' target='_blank'>%s</a> - %s" %\
            (r.pk, r, r.get_status_display()) for r in self.get_dev_qa_req(obj)]
        return "<br />".join(rtn)

    def get_iap_info(self, obj, sp='<br />'):
        info = obj.app.iapinfo_set.filter(status='F')
        iaps = []
        for f in info:
            iaps += list(f.iap_set.all())
        return sp.join(['%s / %s / %s / %s' % (i.type, i.price, i.prd_id, i.name)\
            for i in iaps])

    def get_dev_qa_req(self, obj, status=[]):
        qs = DevQAInfo.objects.filter(app=obj.app, version=obj.version)
        if status:
            qs = qs.filter(status__in=status)
        return qs

    def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
        db = kwargs.get('using')
        if db_field.name in self.raw_id_fields:
            kwargs['widget'] = CustomForeignKeyRawIdWidget(db_field.rel,
                                    self.admin_site, using=db)
        elif db_field.name in self.radio_fields:
            kwargs['widget'] = widgets.AdminRadioSelect(attrs={
                'class': get_ul_class(self.radio_fields[db_field.name]),
            })
            kwargs['empty_label'] = db_field.blank and _('None') or None

        return db_field.formfield(**kwargs)

    def get_actions(self, request):
        """
        remove delete action
        """
        actions = super(SubInfoAdmin, self).get_actions(request)
        if actions.get('delete_selected'):
            del actions['delete_selected']
        return actions

#    def get_changelist_formset(self, request, **kwargs):
#        """
#        Returns a FormSet class for use on the changelist page if list_editable
#        is used.
#        """
#        if not request.user.is_superuser and\
#        not request.user.groups.filter(name='Post-production Staff').exists():
#            list_editable = ()
#        else:
#            list_editable = self.list_editable
#
#        defaults = {
#            "formfield_callback": partial(self.formfield_for_dbfield, request=request),
#        }
#        defaults.update(kwargs)
#        return modelformset_factory(self.model,
#            self.get_changelist_form(request), extra=0,
#            fields=list_editable, **defaults)

    def response_change(self, request, obj):
        if not request.user.is_superuser and\
        not request.user.groups.filter(name='Post-production Staff').exists():
            if obj.validation == 'I':
                obj.validation = 'P'
                obj.save()
                Notice.objects.notice_manager('Submission Request Updated',
                    self.notice_content.format(obj.pk, obj.request_id,
                        obj.app.prj_code, obj.app.app_name.encode('utf8'), obj.version))
#                email_sending('Submission Request Updated.',
#                    'Submission Request ID: %s <br />\
#                    App Code: %s <br />\
#                    App Name: %s <br />\
#                    App Version: %s <br/>' % (obj.request_id, obj.app.prj_code,
#                                              obj.app.app_name, obj.version),
#                    to=[i[1] for i in settings.MANAGERS])
        return admin.ModelAdmin.response_change(self, request, obj)

    def save_model(self, request, obj, form, change):
        if not change:
            obj.editor = request.user.email
            current_year = timezone.now().year
            current_month = timezone.now().month
            current_day = timezone.now().day
            latest = SubInfo.objects.filter(create_time__year=current_year,
                create_time__month=current_month, create_time__day=current_day).order_by('-request_id')[:1]
            if latest:
                latest = latest[0]
                num = int(latest.request_id[-2:]) + 1
            else:
                num = 1
            obj.request_id = 'RSUB-%s%s%s%s' % (current_year, '%02i' % current_month,
                '%02i' % current_day, '%02i' % num)
            obj.save()
            # send email to notice admin request add
            Notice.objects.notice_manager('New Submission Request',
                self.notice_content.format(obj.pk, obj.request_id,
                    obj.app.prj_code, obj.app.app_name.encode('utf8'), obj.version))
#            email_sending('New Submission Request.',
#                'Submission Request ID: %s <br />\
#                App Code: %s <br />\
#                App Name: %s <br />\
#                App Version: %s <br />' % (obj.request_id, obj.app.prj_code,
#                                           obj.app.app_name, obj.version),
#                to=[i[1] for i in settings.MANAGERS])
        if not obj.rating:
            sr = request.REQUEST.get('select_rating')
            tr = request.REQUEST.get('text_rating', '')
            if sr:
                if tr:
                    obj.rating = sr + ", " + tr
                else:
                    obj.rating = sr
            else:
                if tr:
                    obj.rating = tr
                else:
                    obj.rating = ''
        obj.territories = request.REQUEST.get('countries')
        obj.save()
        # get submission status from Publish System, no longer need edit in PTS
#        if 'status' in form.changed_data:
#            if obj.status == 'S':
#                # mark version log status submitted when sub info submitted
#                if obj.app.app_store == 'Google Play':
#                    AppVersion.objects.filter(app=obj.app, code=obj.version,
#                        status__in=['I', 'O']).update(status='L', date_submitted=obj.app_submit_date)
#                else:
#                    AppVersion.objects.filter(app=obj.app, code=obj.version,
#                        status__in=['I', 'O']).update(status='S', date_submitted=obj.app_submit_date)
#                # create a review status obj when sub info submitted
#                ds = 'PR'
#                ad = None
#                rd = None
#                if obj.app.app_store == 'Google Play':
#                    ds = 'RE'
#                    ad = obj.app_submit_date
#                    rd = obj.app_submit_date
#                ReviewStatus.objects.get_or_create(sub_info=obj,
#                    defaults={'status': ds, 'store_accept_date': ad,
#                              'release_date': rd})
#            elif obj.status == 'O':
#                AppVersion.objects.filter(app=obj.app, code=obj.version, status='I').update(status='O')
#
#        if 'app_submit_date' in form.changed_data:
#            AppVersion.objects.filter(app=obj.app, code=obj.version).update(\
#                date_submitted=obj.app_submit_date)  # update the submitted date in AppVersion obj.

        if 'validation' in form.changed_data:
            if obj.validation == 'V':
                ctx = {'request_id': obj.request_id, 'create_time': str(obj.create_time),
                       'editor': obj.editor, 'app_code': obj.app.prj_code,
                       'app_name': obj.app.app_name, 'product_id': obj.app.prd_id,
                       'studio_code': obj.app.studio.studio_code,
                       'version': obj.version, 'type': self.get_type(obj),
                       'purpose': self.get_purpose(obj), 'note': self.get_notes(obj),
                       'is_resub': obj.get_is_resub_display(),
                       'resub_req': "<br />".join(obj.get_resub_req()),
                       'owner': self.get_product_owner(obj),
                       'production_team': self.get_production_team(obj),
                       'programmer': self.get_programmer(obj),
                       'ref_id': self.get_ref_id(obj),
                       'app_store': obj.app.app_store, 'bundle_id': obj.app.get_full_bundle_id(),
                       'app_id': obj.app.app_id, 'display_name': self.get_display_name(obj),
                       'ads': 'Yes' if self.get_has_ads(obj) else 'No',
                       'ads_requests': '<br />'.join([a.request_id for a in obj.app.adsinfo_set.all()]),
                       'cross': 'Yes' if self.get_has_cross_promo(obj) else 'No',
                       'cross_promo_requests': '<br />'.join([a.request_id for a in obj.app.adsinfo_set.filter(cross_promo='Y')] +\
                                                             [i.request_id for i in obj.app.crosspromoreq_set.all()]),
                       'iap': 'Yes' if self.get_has_iap(obj) else 'No',
                       'iap_requests': '<br />'.join([i.request_id for i in obj.app.iapinfo_set.all()]),
                       'settings': self.get_special_settings(obj),
                       'sd_local': self.get_submission_doc_local(obj),
                       'sd_dropbox': self.get_submission_doc_remote(obj),
                       'edsr': obj.edsr, 'price': obj.price,
                       'territories': obj.get_territories(),
                       'update_meta': self.get_update_meta(obj),
                       'update_assets': self.get_update_assets(obj),
                       'rating': obj.rating, 'notes': obj.notes,
                       'release': obj.get_release_display(),
                       'validation': obj.get_validation_display(),
                       'valid_date': str(obj.valid_date), 'validation_notes': obj.validation_notes}
                rtn = api_call('%s%s' % (settings.PS_DOMAIN, settings.PS_CREATE_SUB),
                    json.dumps({'request': ctx}), 'POST', {'Content-Type': 'application/json'})
                if not rtn.get('code') == 1:
                    mail_admins('New Submission Request Sent Failed', rtn.get('msg'))
                    self.message_user(request, 'Server Error', messages.ERROR)
                    return
                # send email to editor notice request valid
                Notice.objects.send_notice('App Submission Request <strong>Sent Successfully</strong>',
                    self.notice_content.format(obj.pk, obj.request_id,
                        obj.app.prj_code, obj.app.app_name.encode('utf8'),
                        obj.version),
                    obj.editor)

                # if the Dev QA Request of this app-version cleared, make Release QA Request
                dev_qa = self.get_dev_qa_req(obj, ['D'])[:1]
                if dev_qa.exists():
                    if not ReleaseQAInfo.objects.filter(dev_qa=dev_qa[0],
                        sub_info=obj, status__in=['P', 'I', 'D', 'O']).exists():
                        ReleaseQAInfo.objects.create(dev_qa=dev_qa[0], sub_info=obj,
                            editor=obj.editor)
                        rtn = api_call('%s%s' % (settings.PS_DOMAIN, settings.PS_CREATE_META),
                            json.dumps({'request': {'request_id': obj.request_id}}),
                                'POST', {'Content-Type': 'application/json'})
                        if not rtn.get('code') == 1:
                            mail_admins('Meta Request Sent Failed', rtn.get('msg'))
                            self.message_user(request, 'Server Error', messages.ERROR)
                            return
#                email_sending('App Submission Request Sent Successfully.',
#                    'Submission Request ID: %s <br />\
#                    App Code: %s <br />\
#                    App Name: %s <br />\
#                    App Version: %s <br />' % (obj.request_id, obj.app.prj_code,
#                                               obj.app.app_name, obj.version),
#                    to=[obj.editor])
                # 2015-06-10: no longer update google sheet
#                basic = [obj.app.app_store, obj.request_id, obj.editor,
#                    obj.create_time, obj.app.prj_code, obj.app.app_name,
#                    obj.version,
#                    self.get_display_name(obj), obj.app.get_full_bundle_id(),
#                    obj.app.app_id, self.get_type(obj),
#                    self.get_special_settings(obj, "\n"),
#                    self.get_purpose(obj, "\n"), self.get_notes(obj, "\n")]
#                ads = ['Yes' if self.get_has_ads(obj) else 'No',
#                       'Yes' if self.get_has_cross_promo(obj) else 'No',
#                       'Yes' if self.get_has_iap(obj) else 'No',
#                       obj.get_is_resub_display(), self.get_product_owner(obj),
#                       self.get_programmer(obj, False)]
#                qa = ['' for i in range(5)]
#                mk = ['' for i in range(9)]
#                if 'UBF' in obj.get_resub_req():  # need QA
#                    qa = [obj.edqa, obj.etqa, obj.notes_to_qa,
#                          self.get_iap_info(obj, "\n")]
#                if 'UMDAMK' in obj.get_resub_req():  # need Marketing
#                    mk = [obj.price, self.get_submission_doc_remote(obj),
#                          obj.edsr, self.get_territories(obj), self.get_update_assets(obj, "\n"),
#                          self.get_update_meta(obj, "\n"), obj.rating, obj.notes,
#                          obj.get_release_display()]
##                update_google_sheet.delay(settings.SUB_REQUEST_FILE, basic + mk + ads + qa)
#                UpdateGoogleSheetThread(settings.SUB_REQUEST_FILE, basic + mk + ads + qa + [self.get_ref_id(obj)]).start()
            elif obj.validation == 'I':
                # send email to editor notice request invalid
                Notice.objects.send_notice('App Submission Request <font color="red">Failed Validation</font>',
                    '''<p>Submission Request ID: <a href='/admin/sub_info/subinfo/{0}/'>{1}</a></p>
                       <p>App Code: <font color='red'>{2}</font></p>
                       <p>App Name: <font color='red'>{3}</font></p>
                       <p>App Version: <font color='red'>{4}</font></p>'''.format(obj.pk, obj.request_id,
                        obj.app.prj_code, obj.app.app_name.encode('utf8'), obj.version),
                    obj.editor)
#                email_sending('App Submission Request Failed Validation.',
#                    'Submission Request ID: %s <br />\
#                    Notes: %s <br />' % (obj.request_id, obj.validation_notes),
#                    to=[obj.editor])
            elif obj.validation == 'C':
                ctx = {'request_id': obj.request_id, 'status': 'cancel'}
                rtn = api_call('%s%s' % (settings.PS_DOMAIN, settings.PS_CANCEL_SUB),
                    json.dumps({'request': ctx}), 'POST', {'Content-Type': 'application/json'})
                if not rtn.get('code') == 1:
                    mail_admins('Cancel Submission Request Sent Failed', rtn.get('msg'))
                    self.message_user(request, 'Server Error', messages.ERROR)
                    return
                # send email to editor notice request cancelled
                Notice.objects.send_notice('App Submission Request <font color="red">Cancelled</font>',
                    self.notice_content.format(obj.pk, obj.request_id,
                        obj.app.prj_code, obj.app.app_name.encode('utf8'), obj.version),
                    obj.editor)
#                email_sending('App Submission Request Canceled.',
#                    'Submission Request ID: %s <br />\
#                    App Code: %s <br />\
#                    App Name: %s <br />\
#                    App Version: %s <br />\
#                    Notes: %s <br />' % (obj.request_id, obj.app.prj_code,
#                                         obj.app.app_name, obj.version,
#                                         obj.validation_notes),
#                    to=[obj.editor])


class ReviewStatusRecordInline(admin.TabularInline):
    model = ReviewStatusRecord
    can_delete = False
    extra = 0
    suit_classes = 'suit-tab suit-tab-status_record'
    readonly_fields = ('status_before', 'status_after', 'editor', 'time')

    def get_formset(self, request, obj=None, **kwargs):
        if obj:
            self.max_num = obj.reviewstatusrecord_set.count()
        return admin.TabularInline.get_formset(self, request, obj=obj, **kwargs)


class ReviewStatusAdmin(admin.ModelAdmin):
    list_display = ('sub_info', 'get_app', 'get_app_store', 'status',
        'get_submitted_date', 'release_date')
    search_fields = ('sub_info__request_id', 'sub_info__app__prj_code')
    list_per_page = 20
    list_filter = ('status', 'sub_info__app__app_store')
    readonly_fields = ('sub_info', 'get_sub_info', 'get_submitted_date',
        'get_app', 'get_app_store', 'get_app_studio', 'get_days_in_review',
        'get_days_to_release', 'get_app_store_link', 'get_app_name')
    inlines = [ReviewStatusRecordInline]
    suit_form_tabs = (('basic', 'Review Status'), ('status_record', 'Status Change Log'))
    fields1 = (None, {
            'classes': ('suit-tab', 'suit-tab-basic'),
            'fields':
            (
            'get_sub_info',
            'get_submitted_date',
            'get_app',
            'get_app_store',
            'get_app_studio',
            'status',
            'store_accept_date',
            'release_date',
            )
        })
    fields2 = ('App Store Info', {
            'classes': ('suit-tab', 'suit-tab-basic'),
            'fields':
            (
            'get_days_in_review',
            'get_days_to_release',
            'get_app_store_link',
            'get_app_name',
            )
        })
    fields3 = (None, {
            'classes': ('suit-tab', 'suit-tab-status_record',),
            'fields': ()
        })
    fieldsets = (
        fields1, fields2, fields3,
    )

    @field('Total Days In Review')
    def get_days_in_review(self, obj):
        submitted_date = obj.sub_info.app_submit_date
        store_accept_date = obj.store_accept_date
        if submitted_date and store_accept_date and store_accept_date >= submitted_date:
            return (store_accept_date - submitted_date).days
        return 'unknown'

    @field('Total Days to Release')
    def get_days_to_release(self, obj):
        submitted_date = obj.sub_info.app_submit_date
        release_date = obj.release_date
        if submitted_date and release_date and release_date >= submitted_date:
            return (release_date - submitted_date).days
        return 'unknown'

    @field('App Store Link', allow_tags=True)
    def get_app_store_link(self, obj):
        if obj.sub_info.app.store_link:
            return "<a href='%s' target='_blank'>%s</a>" % (obj.sub_info.app.store_link,
                obj.sub_info.app.store_link)
        return ""

    @field('App Name (Release)')
    def get_app_name(self, obj):
        return ""

    @field('Submission Request', allow_tags=True)
    def get_sub_info(self, obj):
        return "<a href='/admin/sub_info/subinfo/%s/' target='_blank'>%s</a>" %\
            (obj.sub_info.pk, obj.sub_info.request_id)

    @field('Date - Submitted', admin_order_field='sub_info__app_submit_date')
    def get_submitted_date(self, obj):
        return obj.sub_info.app_submit_date

    @field('App', allow_tags=True, admin_order_field='sub_info__app__prj_code')
    def get_app(self, obj):
        return "<a href='/admin/app_info/app/%s/' target='_blank'>%s</a>" %\
            (obj.sub_info.app.pk, obj.sub_info.app)

    @field('App Store', allow_tags=True, admin_order_field='sub_info__app__app_store')
    def get_app_store(self, obj):
        return obj.sub_info.app.get_app_store_icon()

    @field('Publish Studio')
    def get_app_studio(self, obj):
        return obj.sub_info.app.studio

    def get_fieldsets(self, request, obj=None):
        if not obj.status == 'RE':
            return (self.fields1, self.fields3)
        return admin.ModelAdmin.get_fieldsets(self, request, obj=obj)

    def has_add_permission(self, request):
        return False

    def get_actions(self, request):
        """
        remove delete action
        """
        actions = super(ReviewStatusAdmin, self).get_actions(request)
        if actions.get('delete_selected'):
            del actions['delete_selected']
        return actions

    def register_apm(self, obj):
        results = []
        app = obj.sub_info.app
        ctx = {'product_id': app.prd_id, 'app_code': app.prj_code,
               'alt_app_code': app.old_prj_code, 'app_name': app.app_name,
               'pub_app_name': app.pub_name, 'bundle_id_prefix': app.bundle_id_prefix,
               'bundle_id_suffix': app.bundle_id_suffix,
               'full_bundle_id': app.get_full_bundle_id(),
               'platform': app.get_platform_display(), 'app_store': app.app_store,
               'apple_id': app.app_id, 'store_link': app.store_link,
               'publish_studio': '%s - %s' % (app.studio.custom_id, app.studio.pub_name),
               'studio_cloud': app.studio.cloud.cloud_id,
               'initial_release_date': str(app.get_initial_release_date()),
               'flurry_key': app.flurry_key, 'division': app.get_division(),
               'team': app.get_team()}
        v = app.appversion_set.filter(code=obj.sub_info.version, status='L')[:1]
        v = v[0] if v else None
        versions = [{'task_id': v.log_id,
                     'coordinator': v.get_coordinator(),
                     'version_num': v.code,
                     'release_date': str(v.date_released) or "",
                     'release_notes': v.change_list,
                     'has_iap': True if v.iap_required == 'Y' else False,
                     'has_ads': True if v.ads_required == 'Y' else False,
                     'has_cross_promo': True if v.cross_promo_required == 'Y' else False}] if v else []
        ctx.update({'versions': versions})
        results.append(ctx)
        data = {'results': results}
        return api_call('%s%s' % (settings.APM_DOMAIN, settings.APM_NEW_RELEASED),
            json.dumps(data), 'POST', {'Content-Type': 'application/json'})

    def save_model(self, request, obj, form, change):
        # create status change log when status changed
        if 'status' in form.changed_data:
            status_before = get_object_or_404(ReviewStatus, pk=obj.pk).status
            status_after = obj.status
            ReviewStatusRecord.objects.create(rs=obj, status_before=status_before,
                status_after=status_after, editor=request.user.username)
            # mark the version of the app lived when status is "Released"
            if obj.status == 'RE':
                obj.sub_info.app.appversion_set.filter(code=obj.sub_info.version,
                    status__in=['I', 'S']).update(status='L')
        obj.save()
        if 'release_date' in form.changed_data:
            obj.sub_info.app.appversion_set.filter(code=obj.sub_info.version,
                status='L').update(date_released=obj.release_date)
            print self.register_apm(obj)


class RejReasonInline(admin.StackedInline):
    model = RejReason
    can_delete = False
    extra = 1

    @field('Details', allow_tags=True)
    def get_detail(self, obj):
        return obj.detail.replace(" ", "&nbsp;").replace("\n", "<br />")

    def get_readonly_fields(self, request, obj=None):
        if not request.user.is_superuser and\
        not request.user.groups.filter(name='Post-production Staff').exists():
            return ('reason', 'get_detail')
        return admin.StackedInline.get_readonly_fields(self, request, obj=obj)

    def get_formset(self, request, obj=None, **kwargs):
        if obj:
            if obj.rejreason_set.exists():
                self.extra = 0
        if not request.user.is_superuser and\
        not request.user.groups.filter(name='Post-production Staff').exists():
            self.exclude = ('detail',)
        return admin.StackedInline.get_formset(self, request, obj=obj, **kwargs)


class RejImgInline(admin.TabularInline):
    model = RejImg
    extra = 1
    form = RejImgForm

    class Media:
        js = ("highslide/highslide-with-gallery.js",
              "base/js/highslide-override-config.js",)
        css = {'all': ('highslide/highslide.css',)}

    @field('Screenshot', allow_tags=True)
    def get_img(self, obj):
        if obj.img:
            mini = get_thumbnail(obj.img, 'x80', upscale=False,
                format=os.path.splitext(obj.img.path)[1].split('.')[1].upper())
            return '''<a
                        title="Click to enlarge"
                        style="width:%spx;display:block;margin:0 0 10px"
                        class="thumbnail highslide"
                        href="%s"
                        onclick="return hs.expand(this)"><img src="%s"></a>'''\
                        % (mini.width, obj.img.url, mini.url)
        return ""

    def get_readonly_fields(self, request, obj=None):
        if not request.user.is_superuser and\
        not request.user.groups.filter(name='Post-production Staff').exists():
            return ('get_img', 'desc')
        return admin.TabularInline.get_readonly_fields(self, request, obj=obj)

    def get_formset(self, request, obj=None, **kwargs):
        if obj:
            if obj.rejimg_set.exists():
                self.extra = 0
        if not request.user.is_superuser and\
        not request.user.groups.filter(name='Post-production Staff').exists():
            self.exclude = ('img',)
        return admin.TabularInline.get_formset(self, request, obj=obj, **kwargs)


class RejActInline(admin.TabularInline):
    model = RejAct
    extra = 1
    can_delete = False

    def get_readonly_fields(self, request, obj=None):
        if not request.user.is_superuser and\
        not request.user.groups.filter(name='Post-production Staff').exists():
            return ('person', 'act', 'date')
        return admin.TabularInline.get_readonly_fields(self, request, obj=obj)

    def get_formset(self, request, obj=None, **kwargs):
        if obj:
            if obj.rejact_set.exists():
                self.extra = 0
        return admin.TabularInline.get_formset(self, request, obj=obj, **kwargs)


class RejectionAdmin(admin.ModelAdmin):
    list_display = ('issue_id', 'get_status', 'get_sub_info', 'get_app', 'get_app_store',
        'get_editor', 'timestamp')
    inlines = [RejReasonInline, RejImgInline, RejActInline]
    raw_id_fields = ('sub_info',)
    search_fields = ('issue_id', 'editor', 'sub_info__request_id')
    list_filter = ('status', 'sub_info__app__app_store')
    fieldsets = (
        (None, {
            'fields':
            (
            'sub_info',
            'timestamp',
            'status',
            )
        }),
    )

    class Media:
        js = ('base/js/RelatedObjectLookups.js', 'base/js/custom_rej_admin.js')

    @field('App Store', allow_tags=True, admin_order_field='sub_info__app__app_store')
    def get_app_store(self, obj):
        return obj.sub_info.app.get_app_store_icon()

    @field('App', allow_tags=True, admin_order_field='sub_info__app__prj_code')
    def get_app(self, obj):
        return "<a href='/admin/app_info/app/%s/' target='_blank'>%s - V%s</a>" %\
            (obj.sub_info.app.id, obj.sub_info.app.__unicode__(), obj.sub_info.version)

    @field('Status', allow_tags=True, admin_order_field='status')
    def get_status(self, obj):
        if obj.status == 'O':
            cls = 'label-important'
        elif obj.status == 'C':
            cls = 'label-success'
        elif obj.status == 'E':
            cls = ''
        elif obj.status == 'H':
            cls = 'label-warning'
        else:
            cls = 'label-info'
        return "<span class='label %s' style='width: 50px;'><center>%s</center></span>" % (cls, obj.get_status_display())

    @field('Submission Request', allow_tags=True, admin_order_field='sub_info')
    def get_sub_info(self, obj):
        return "<a href='%s%s/' target='_blank'>%s</a>" % ('/admin/sub_info/subinfo/',
            obj.sub_info_id, obj.sub_info)

    @field('Issue Created By', admin_order_field='editor')
    def get_editor(self, obj):
        return obj.editor.split('@')[0]

    def get_readonly_fields(self, request, obj=None):
        if obj:
            if not request.user.is_superuser and\
            not request.user.groups.filter(name='Post-production Staff').exists():
                return ('sub_info', 'get_sub_info', 'timestamp', 'status')
            return ('sub_info', 'get_sub_info')
        return self.readonly_fields

    def get_fieldsets(self, request, obj=None):
        if obj:
            return ((None, {'fields':
            (
            'get_sub_info',
            'timestamp',
            'status',
            )
        }),)
        if self.declared_fieldsets:
            return self.declared_fieldsets
        form = self.get_form(request, obj)
        fields = list(form.base_fields) + list(self.get_readonly_fields(request, obj))
        return [(None, {'fields': fields})]

    def get_actions(self, request):
        """
        remove delete action
        """
        actions = super(RejectionAdmin, self).get_actions(request)
        if actions.get('delete_selected'):
            del actions['delete_selected']
        return actions

    def save_model(self, request, obj, form, change):
        if not change:
            obj.editor = request.user.email
            current_year = timezone.now().year
            current_month = timezone.now().month
            current_day = timezone.now().day
            latest = Rejection.objects.filter(create_time__year=current_year,
                create_time__month=current_month, create_time__day=current_day).order_by('-issue_id')
            if latest:
                latest = latest[0]
                num = int(latest.issue_id[-2:]) + 1
            else:
                num = 1
            obj.issue_id = 'IREJ-%s%s%s%s' % (current_year, '%02i' % current_month,
                '%02i' % current_day, '%02i' % num)
            obj.save()
            Notice.objects.send_notice('App <font color="red">Rejected</font>',
                '''
                <p>Your app: <a target='_blank' href='/admin/app_info/app/{0}/'>{1}</a> V{2}</p>
                <p>Submission Request: <a target='_blank' href='/admin/sub_info/subinfo/{3}/'>{4}</a>
                was <font color='red'>Rejected</font> by {5}</p>
                <p>Rejection Issue: <a target='_blank' href='/admin/sub_info/rejection/{6}/'>{7}</a> was created
                '''.format(obj.sub_info.app.pk, obj.sub_info.app.prj_code, obj.sub_info.version,
                           obj.sub_info.pk, obj.sub_info.request_id, obj.sub_info.app.app_store,
                           obj.pk, obj.issue_id),
                obj.editor)
#            email_sending('App Rejected',
#                'Your app <font color="red">%s V%s</font> (Submission Request: %s) was rejected by %s<br />Rejection Issue: %s was created' %\
#                (obj.sub_info.app.prj_code, obj.sub_info.version,
#                 obj.sub_info.request_id, obj.sub_info.app.app_store, obj.issue_id),
#                [obj.sub_info.editor])
        obj.save()
        if 'status' in form.changed_data:
            Notice.objects.send_notice('Rejection Issue Status Changed',
                '''
                <p>Status of your Rejection Issue <a target='_blank' href='/admin/sub_info/rejection/{0}/'>{1}</a>
                has been changed to: <font color='red'>{2}</font></p>
                '''.format(obj.pk, obj.issue_id, obj.get_status_display().upper()),
                obj.sub_info.editor)
#            email_sending('Rejection Issue Status Changed',
#                'Status of your Rejection Issue %s has been changed to: <font color="red">%s</font>' %\
#                (obj.issue_id, obj.get_status_display().upper()),
#                [obj.sub_info.editor])


#admin.site.register(Rejection, RejectionAdmin)
#admin.site.register(ReviewStatus, ReviewStatusAdmin)
admin.site.register(SubInfo, SubInfoAdmin)
